import 'package:built_collection/built_collection.dart';
import 'package:equatable/equatable.dart';
import 'package:mobile_app.core/core/domain/entities/dialect.dart';
import 'package:mobile_app.core/core/domain/entities/email_app.dart';
import 'package:mobile_app.core/core/domain/entities/settings/image_settings.dart';
import 'package:mobile_app.core/core/domain/entities/learning_content/collection_list_item/collection_list_item.dart';
import 'package:mobile_app.core/core/domain/entities/learning_content/lexical_item/lexical_item.dart';
import 'package:mobile_app.core/core/domain/entities/learning_info/learning_info.dart';
import 'package:mobile_app.core/core/domain/entities/premium_access_status.dart';
import 'package:mobile_app.core/core/domain/helpers/handle_learning_activity/helper.dart';
import 'package:mobile_app.core/core/domain/services/image_service/service.dart';
import 'package:mobile_app.home.core/core/domain/helpers/get_lexical_item_effective_image_path/helper.dart';
import 'package:mobile_app.home.core/core/domain/helpers/is_lexical_item_safe_to_pronounce/helper.dart';
import 'package:mobile_app.home.learning.spaced_repetitions/spaced_repetition_page/domain/entities/card_infos/card_info.dart';
import 'package:mobile_app.home.learning.spaced_repetitions/spaced_repetition_page/domain/helpers/get_unspecified_lexical_item_exposed_card_actions/helper.dart';

part 'result.dart';

abstract class ExposeUnspecifiedLexicalItemObscureCard {
  UnspecifiedLexicalItemObscureCardExposureResult call({
    required UnspecifiedLexicalItemObscureCardInfo currentCardInfo,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
    required BuiltList<CollectionListItem> collectionListItems,
    required PremiumAccessStatus premiumAccessStatus,
    required BuiltList<EmailApp> availableEmailApps,
    required Dialect dialect,
    required BuiltMap<Dialect, BuiltSet<String>> unsafeToPronounceLexicalItemTitleMap,
    required LearningInfo learningInfo,
    required ImageSettings imageSettings,
  });
}

class ExposeUnspecifiedLexicalItemObscureCardImpl
    implements ExposeUnspecifiedLexicalItemObscureCard {
  const ExposeUnspecifiedLexicalItemObscureCardImpl({
    required GetLexicalItemEffectiveImagePath getLexicalItemEffectiveImagePath,
    required GetUnspecifiedLexicalItemExposedCardActions
        getUnspecifiedLexicalItemExposedCardActions,
    required HandleLearningActivity handleLearningActivity,
    required IsLexicalItemSafeToPronounce isLexicalItemSafeToPronounce,
    required ImageService imageService,
  })  : _getLexicalItemEffectiveImagePath = getLexicalItemEffectiveImagePath,
        _getUnspecifiedLexicalItemExposedCardActions = getUnspecifiedLexicalItemExposedCardActions,
        _handleLearningActivity = handleLearningActivity,
        _isLexicalItemSafeToPronounce = isLexicalItemSafeToPronounce,
        _imageService = imageService;

  final GetLexicalItemEffectiveImagePath _getLexicalItemEffectiveImagePath;
  final GetUnspecifiedLexicalItemExposedCardActions _getUnspecifiedLexicalItemExposedCardActions;
  final HandleLearningActivity _handleLearningActivity;
  final IsLexicalItemSafeToPronounce _isLexicalItemSafeToPronounce;

  final ImageService _imageService;

  @override
  UnspecifiedLexicalItemObscureCardExposureResult call({
    required UnspecifiedLexicalItemObscureCardInfo currentCardInfo,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
    required BuiltList<CollectionListItem> collectionListItems,
    required PremiumAccessStatus premiumAccessStatus,
    required BuiltList<EmailApp> availableEmailApps,
    required Dialect dialect,
    required BuiltMap<Dialect, BuiltSet<String>> unsafeToPronounceLexicalItemTitleMap,
    required LearningInfo learningInfo,
    required ImageSettings imageSettings,
  }) {
    final lexicalItem = currentCardInfo.lexicalItem;

    final updatedCurrentCardInfo = currentCardInfo.copyWith(
      finishEvent: () => UnspecifiedLexicalItemObscureCardFinishEvent.exposed,
    );

    final exposedCardActions = _getUnspecifiedLexicalItemExposedCardActions(
      lexicalItem: lexicalItem,
      collectionListItems: collectionListItems,
      lexicalItemMap: lexicalItemMap,
      premiumAccessStatus: premiumAccessStatus,
      availableEmailApps: availableEmailApps,
    );

    final safeToPronounce = _isLexicalItemSafeToPronounce(
      lexicalItem: lexicalItem,
      dialect: dialect,
      unsafeToPronounceLexicalItemTitleMap: unsafeToPronounceLexicalItemTitleMap,
    );

    final imagePath = _getLexicalItemEffectiveImagePath(
      lexicalItem: lexicalItem,
      imageEnablementEffective: imageSettings.imageEnablementEffective,
      cachedImagePathMap: _imageService.cachedImagePathMap,
    );

    final exposedCardInfo = UnspecifiedLexicalItemExposedCardInfo(
      lexicalItem: lexicalItem,
      cardActions: exposedCardActions,
      safeToPronounce: safeToPronounce,
      finishEvent: UnspecifiedLexicalItemExposedCardFinishEvent.none,
      imagePath: imagePath,
    );

    final updatedLearningInfo = _handleLearningActivity(
      learningInfo: learningInfo,
    );

    final result = UnspecifiedLexicalItemObscureCardExposureResult(
      currentCardInfo: exposedCardInfo,
      previousCardInfo: updatedCurrentCardInfo,
      learningInfo: updatedLearningInfo,
    );

    return result;
  }
}
